package com.joysuch.wwyt.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.google.gson.reflect.TypeToken;
import com.joysuch.wwyt.util.GsonUtils;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.formula.functions.T;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @author qingzhou
 * 2019-10-23
 */
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RedisClient {

    private final RedissonClient redissonClient;

    private void checkRedisKeyFormat(String key) {
        if (Strings.isNullOrEmpty(key)) {
            throw new IllegalArgumentException("key is null or empty");
        }
        int idx = key.indexOf(":");
        if (idx == -1 || idx == key.length() - 1) {
            throw new IllegalArgumentException("key must be \"prefix:biz-id\" format");
        }
    }

    public void hput(String key, String hashKey, String value) {
        checkRedisKeyFormat(key);
        redissonClient.getMap(key).put(hashKey, value);
    }

    public <K, V> void hput(String key, K hashKey, V value) {
        checkRedisKeyFormat(key);
        redissonClient.getMap(key).put(hashKey, value);
    }

    public void expireMap(String key, long timeToLive, TimeUnit timeUnit) {
        redissonClient.getMap(key).expire(timeToLive, timeUnit);
    }

    public String hget(String key, String hashKey) {
        return (String) redissonClient.getMap(key).get(hashKey);
    }

    public <K, V> V hget(String key, K hashKey, Class<V> result) {
        if (redissonClient.getMap(key).get(hashKey) != null) {
            String data = JSONObject.toJSONString(redissonClient.getMap(key).get(hashKey));
            Object obj = JSON.parse(data);
            return JSONObject.parseObject(obj.toString(), result);
        }
        return null;
    }

    public <K, V> List<V> hget(String key, K hashKey) {
        if (redissonClient.getMap(key).get(hashKey) != null) {
            String data = (String) redissonClient.getMap(key).get(hashKey);
            return GsonUtils.fromJson(data, new TypeToken<List<V>>() {
            }.getType());
        }
        return null;
    }

    public boolean delMap(String key) {
        return redissonClient.getMap(key).delete();
    }

    public <K> void removeMapKey(String key, K hashKey) {
        redissonClient.getMap(key).remove(hashKey);
    }

    public void set(String key, String val) {
        redissonClient.getBucket(key).set(val);
    }

    public void setEx(String key, String value, long timeToLive, TimeUnit timeUnit) {
        redissonClient.getBucket(key).set(value, timeToLive, timeUnit);
    }

    public Boolean trySetAsync(String key, String value, long timeToLive, TimeUnit timeUnit) throws ExecutionException, InterruptedException {
        return redissonClient.getBucket(key).trySetAsync(value, timeToLive, timeUnit).get();
    }


    public void expireString(String key, long timeToLive, TimeUnit timeUnit) {
        redissonClient.getBucket(key).expire(timeToLive, timeUnit);
    }

    public long getExpireTime(String key) {
        return redissonClient.getBucket(key).remainTimeToLive();
    }

    public void removeKey(String key) {
        redissonClient.getBucket(key).delete();
    }

    public String get(String key) {
        return (String) redissonClient.getBucket(key).get();
    }

    public RMap<String, String> getMap(String key) {
        return redissonClient.getMap(key);
    }

    public RLock getLock(String key) {
        return redissonClient.getLock(key);
    }

    public <V> RList<V> getList(String key) {
        return redissonClient.getList(key);
    }


    public void addList(String key, Long value) {
        redissonClient.getList(key).add(value);
    }

    public void setList(String key, Object value) {
        redissonClient.getList(key).add(value);
    }
    public void setList(String key, List<Object> value) {
        redissonClient.getList(key).addAll(value);
    }

    public void updateList(String key,Integer index, Object value) {
        redissonClient.getList(key).set(index,value);
    }

    public void removeListValue(String key,Object value) {
         redissonClient.getList(key).remove(value);
    }



    public void removeList(String key) {
        redissonClient.getList(key).delete();
    }


    public void setZSet(String key, String value, long score) {
        RScoredSortedSet<String> set = redissonClient.getScoredSortedSet(key);
        set.add(score, value);
    }

    public RScoredSortedSet<String> getZSet(String key) {
        return redissonClient.getScoredSortedSet(key);
    }

    public Long getZSetScore(String key, String v) {
        RScoredSortedSet<String> scoredSortedSet = redissonClient.getScoredSortedSet(key);
        return scoredSortedSet.getScore(v).longValue();
    }

    public void removeZSet(String key, String removeKey) {
        RScoredSortedSet<String> set = redissonClient.getScoredSortedSet(key);
        set.remove(removeKey);
    }


}
